﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TomanuExtensions;

namespace AmiEmuLib.AmigaMachine.Audio
{
    /// <summary>
    /// Caluclate event cycles, without rounding error, without loosing precisions with big number.
    /// </summary>
    public class EventCalculator
    {
        /// <summary>
        /// Custom cycles per event period.
        /// </summary>
        private double m_cycles_per_event;

        /// <summary>
        /// Custom cycles per event period - fraction.
        /// </summary>
        private double m_cycles_per_event_fraction;

        /// <summary>
        /// Custom cycles per event period.
        /// </summary>
        private int m_cycles_per_event_rounded;

        /// <summary>
        /// To precise calculate next event custom cycle even on big numebers.
        /// </summary>
        private double m_event_cycle_fraction;

        /// <summary>
        /// Custom cycle of event.
        /// </summary>
        public long EventCycle { get; private set; }

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="a_config"></param>
        public EventCalculator(double a_cycles_per_event)
        {
            m_cycles_per_event = a_cycles_per_event;
            m_cycles_per_event_fraction = a_cycles_per_event.Fraction();
            m_cycles_per_event_rounded = a_cycles_per_event.Floor();
            NextEventCycle();
        }

        /// <summary>
        /// Calculate next sample cycle.
        /// </summary>
        public void NextEventCycle()
        {
            double frac = m_event_cycle_fraction + m_cycles_per_event_fraction;
            int rounded = frac.Round();
            m_event_cycle_fraction = frac - rounded;
            EventCycle += m_cycles_per_event_rounded + rounded;
        }

        internal void Test_Set(double a_event_cycle_fraction, long a_event_cycle)
        {
            EventCycle = a_event_cycle;
            m_event_cycle_fraction = a_event_cycle_fraction;
        }
    }
}
